//
//  ExchangeMethodViewController.m
//  ObjectCProject
//
//  Created by lvfeijun on 2021/5/21.
//
/*
 LLDB 调试了应用
 LLDB-debugsever（附加你的应用）
 Process trace(P trace)进程跟踪
 控制了当前进程
 */

#import "ExchangeMethodViewController.h"
//ptrace
#import "ptrace__jun.h"
// dlopen
#include <dlfcn.h>
//run time
#import <objc/runtime.h>

@interface ExchangeMethodViewController ()

@end

@implementation ExchangeMethodViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    //获取句柄
//    void *handle = dlopen("/usr/lib/system/libsystem_kernel.dylib", RTLD_LAZY);
//    //拿到ptrace指针
//    int (*ptrace_p)(int _request, pid_t _pid,caddr_t _addr,int _data);
//    ptrace_p = dlsym(handle, "ptrace");
//    if (!ptrace_p) {
//        return;
//    }
//    ptrace_p(PT_DENY_ATTACH, 0, 0, 0);
//
//    //利用ptrace防护debugserver
//    /*
//       arg1:ptrace 要做的事情
//       arg2:要操作的进程的id
//       arg3(地址)\arg4(数据)：取决于第一个参数
//       */
//      ptrace(PT_DENY_ATTACH, 0, 0, 0);
//    /*
//     运行--附加闪退
//     点击--正常使用没问题
//     */
    
    CGFloat x = 150;
    UIButton *bt = [[UIButton alloc]initWithFrame:CGRectMake(0, x, 320, 50)];
    [bt setTitle:@"log1Action" forState:UIControlStateNormal];
    [bt addTarget:self action:@selector(log1Action:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:bt];
    x += 50;
    
    bt = [[UIButton alloc]initWithFrame:CGRectMake(0, x, 320, 50)];
    [bt setTitle:@"log2Action" forState:UIControlStateNormal];
    [bt addTarget:self action:@selector(log2Action:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:bt];
    x += 50;
    
    bt = [[UIButton alloc]initWithFrame:CGRectMake(0, x, 320, 50)];
    [bt setTitle:@"log3Action" forState:UIControlStateNormal];
    [bt addTarget:self action:@selector(log3Action:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:bt];
    x += 50;
    
    bt = [[UIButton alloc]initWithFrame:CGRectMake(0, x, 320, 50)];
    [bt setTitle:@"log1ActionHook" forState:UIControlStateNormal];
    [bt addTarget:self action:@selector(log1ActionHook:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:bt];
    x += 50;
    
    bt = [[UIButton alloc]initWithFrame:CGRectMake(0, x, 320, 50)];
    [bt setTitle:@"log2ActionHook" forState:UIControlStateNormal];
    [bt addTarget:self action:@selector(log2ActionHook:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:bt];
    x += 50;
    
}
- (void)log1Action:(id)sender {
    NSLog(@"->1<-");
}

- (void)log2Action:(id)sender {
    NSLog(@"->2<-");
}

- (void)log3Action:(id)sender {
    NSLog(@"->3<-");
}

- (void)log1ActionHook:(id)sender {
    NSLog(@"log1Action 交换完成");
    [self exchangeInstanceMethod:[self class] method1Sel:@selector(log1Action:) method2Sel:@selector(new_log1Action:)];
}

- (void)log2ActionHook:(id)sender {
    NSLog(@"log2Action 交换完成");
    
    Method new_method = class_getInstanceMethod([self class], @selector(new_log2Action:));
    IMP new_methodIMP = method_getImplementation(new_method);
    const char *typeEncoding = method_getTypeEncoding(new_method);
    class_replaceMethod([self class], @selector(log2Action:), new_methodIMP, typeEncoding);
}

IMP (*old_onMethod)(id self,SEL _cmd);
- (void)log3ActionHook:(id)sender {
    //GET & SET
    Method onLog3Action = class_getInstanceMethod([self class], sel_registerName("log3Action:"));
    //1.保存原始的IMP
    old_onMethod = method_getImplementation(onLog3Action);
    //2.SET
    method_setImplementation(onLog3Action, (IMP)new_log3Action);
}

- (void)new_log1Action:(id)sender {
    NSLog(@"->1<-来不了了");
}

- (void)new_log2Action:(id)sender {
    NSLog(@"->2<-来不了了");
}

void new_log3Action(id self,SEL _cmd,id sender){
    NSLog(@"->3<-来不了了");
}


- (void)exchangeInstanceMethod:(Class)anClass method1Sel:(SEL)method1Sel method2Sel:(SEL)method2Sel {
    Method originalMethod = class_getInstanceMethod(anClass, method1Sel);
    Method swizzledMethod = class_getInstanceMethod(anClass, method2Sel);
    
    BOOL didAddMethod =
    class_addMethod(anClass,
                    method1Sel,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(anClass,
                            method2Sel,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    }
    
    else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
